package com.wframe.project.jnd.wx.controller;

import com.alibaba.fastjson.JSON;
import com.frame.database.JdataBean;
import com.frame.util.DataConvert;
import com.wframe.project.jnd.entity.Promotion;
import com.wframe.project.jnd.rest.util.*;
import com.wframe.project.jnd.services.*;
import com.wframe.project.jnd.util.PromotionBuilder;
import com.wframe.project.jnd.util.PromotionBuilderFactory;
import com.wframe.project.jnd.util.WebUtils;
import com.wframe.project.jnd.vo.CartBean;
import com.wframe.project.jnd.vo.CartItem;
import com.wframe.project.jnd.vo.CartProductVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by lwb on 2017/4/13.
 */
@RequestMapping("/we/order")
@Controller
public class WechatOrderController extends BaseController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductService productService;

    @Autowired
    private AddressService addressService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private PromotionService promotionService;

    /**
     * 加载订单详情信息
     *
     * @return
     */
    @RequestMapping(value = "/{orderCode}", method = RequestMethod.GET)
    public String getOrder(@PathVariable String orderCode, Model model) throws ClientException {
        SessionUser sessionUser = WebSession.getWbUser(session);
        if (sessionUser == null) {
            return "redirect:/we/user/login";
        }

        String userid = sessionUser.getUserid();
        if (!WebSession.checkWbUserAuth(userid)) {
            return "redirect:/user/certification";
        }

        List<Map> products = orderService.queryOrderProduct(orderCode);
        JdataBean order = orderService.getOrderByCode(orderCode);
        JdataBean address = addressService.getCompanyAddress(userid);

        order.put("paytype", 2);

        double payMoney = order.getDouble("pay_money");//支付金额
        model.addAttribute("hasCoupon", couponService.isExist(userid, payMoney, UserService.UserSourceEnum.WECHAT.ordinal()));
        int totalAmout = orderService.queryOrderProductTotalAmount(orderCode);
        model.addAttribute("totalAmout", totalAmout);
        Map<String, Object> orderMap = (Map<String, Object>) session.getAttribute(orderCode);
        if (orderMap != null) {
            Object orderbz = orderMap.get("orderbz");
            Object paytype = orderMap.get("paytype");
            Object offerMoney = orderMap.get("offerMoney");
            if (offerMoney != null || StringUtils.trimToNull(String.valueOf(orderbz)) != null || StringUtils.trimToNull(String.valueOf(paytype)) != null) {
                order.put("orderbz", orderbz);
                order.put("paytype", paytype);

                double offermoney = Double.parseDouble(String.valueOf(offerMoney));
                model.addAttribute("offerMoney", offermoney < payMoney ? offermoney : payMoney);
                payMoney = DataConvert.doubleSub(payMoney, offermoney);
            }
            //session.removeAttribute(orderCode);
        }

        model.addAttribute("products", products);
        model.addAttribute("order", order.getDataMap());
        model.addAttribute("address", address.getDataMap());

        if (payMoney < 0) {
            payMoney = 0;
        }
        payMoney += order.getDouble("fare_money");
        model.addAttribute("paymoney", payMoney);
        productService.queryPricegrade(userid, products);//价格等级

        return "/wesite/view/order/submit";
    }


    /**
     * 显示支付方式
     *
     * @return
     */
    @RequestMapping(value = "/availablePayway/{orderCode}", method = RequestMethod.GET)
    public String availablePayway(@PathVariable("orderCode") String orderCode,
                                  @RequestParam("bz") String orderbz, Model model, HttpSession session) {
        if (!WebSession.checkLoginStatus(session)) {
            return "/wesite/view/sign/login";
        }
        model.addAttribute("code", orderCode);
        model.addAttribute("orderbz", orderbz);
        return "/wesite/view/order/select-payway";
    }

    /**
     * 选择支付方式
     *
     * @return
     */
    @RequestMapping(value = "/selectedPayway/{orderCode}/{payType}", method = RequestMethod.GET)
    public String selectPayway(@PathVariable("orderCode") String orderCode,
                               @PathVariable("payType") Integer payType,
                               @RequestParam("bz") String orderbz) {
        Map<String, Object> orderMap = (Map<String, Object>) session.getAttribute(orderCode);
        if (orderMap == null) {
            orderMap = new HashMap<>();
        }
        orderMap.put("payType", payType);
        orderMap.put("orderbz", orderbz);
        session.setAttribute(orderCode, orderMap);

        return "redirect:/we/order/" + orderCode;
    }

    /**
     * 提交订单
     *
     * @return
     */
    @RequestMapping(value = "/submittedOrder/{orderCode}", method = RequestMethod.POST)
    @ResponseBody
    public String submitOrder(@PathVariable("orderCode") String orderCode,
                              @RequestParam("bz") String orderbz,
                              @RequestParam(value = "paytype", defaultValue = "2") Integer paytype,
                              @RequestParam(value = "deliverstype", defaultValue = "1") Integer deliverstype,
                              @RequestParam(value = "isinvoice", defaultValue = "1") Integer isinvoice) throws ClientException {

        SessionUser sessionUser = WebSession.getWbUser(session);
        if (sessionUser == null) {
            throw new ClientException(CodeEnum.LoginOut);
        }

        String userid = sessionUser.getUserid();
        if (!WebSession.checkWbUserAuth(userid)) {
            throw new ClientException(CodeEnum.NoAuth);
        }

        JdataBean order = orderService.getOrderByCode(orderCode);
        if (!order.getString("userid").equalsIgnoreCase(userid)) {
            throw new ClientException(CodeEnum.ILLEGAL_REQUEST);
        }

        JdataBean address = addressService.getCompanyAddress(userid);
        JdataBean bean = new JdataBean();

        bean.put("id", order.getString("id"));
        bean.put("paytype", paytype);
        bean.put("bz", orderbz);
        bean.put("source", UserService.UserSourceEnum.WECHAT.ordinal());
        bean.put("deliverstype", deliverstype);
        bean.put("isinvoice", isinvoice);
        bean.put("receipt_user", address.getString("getuser"));
        bean.put("receipt_phone", address.getString("phone"));
        bean.put("receipt_shen", address.getString("shen"));
        bean.put("receipt_shi", address.getString("shi"));
        bean.put("receipt_qu", address.getString("qu"));
        bean.put("receipt_address", address.getString("address"));

        Map<String, Object> orderMap = (Map<String, Object>) session.getAttribute(orderCode);
        double paymoney = order.getDouble("pay_money");//支付金额
        JsonReturn json = new JsonReturn();
        try {
            if (orderMap != null) {
                Object couponId = orderMap.get("couponId");
                if (couponId != null) {
                    String couponid = WebUtils.aesDecrypt(couponId.toString());
                    if (couponService.isUsable(couponid, userid, UserService.UserSourceEnum.WECHAT.ordinal(), paymoney)) {
                        double offermoney = couponService.getCoupon(couponid).getDouble("offer_money");
                        //使用优惠劵
                        bean.put("yh_money", offermoney < paymoney ? offermoney : paymoney);
                        paymoney = DataConvert.doubleSub(paymoney, offermoney);
                        bean.put("couponid", couponid);
                    } else {
                        throw new ClientException(CodeEnum.ILLEGAL_COUPON);
                    }
                }
            }

            paymoney += order.getDouble("fare_money");
            if (paymoney < 0) {
                paymoney = 0;
            }
            bean.put("pay_money", paymoney);
            String paycode = orderService.submitOrder(order.getString("userid"), bean, order.getString("cartids"), order.getString("code"));
            if (paytype == 2) {
                orderService.orderOk(paycode);
            }


            JdataBean redata = new JdataBean();
            redata.put("paymoney", paymoney);
            redata.put("ordercode", orderCode);
            redata.put("paytype", paytype);
            redata.put("orderok", "true");
            json.putData(redata);
            return json.toString();
        } catch (Exception e) {
            return json.toErrorString(this.getClass(), e);
        }

    }

    /**
     * 显示订单提交成功页
     *
     * @return
     */
    @RequestMapping(value = "/showorderOk/{ordercode}/{paymoney}/{paytype}", method = RequestMethod.GET)
    public String showOrderOk(@PathVariable("ordercode") String ordercode,
                              @PathVariable("paymoney") String paymoney,
                              @PathVariable("paytype") String paytype,
                              HttpSession session, Model model) {
        if (!WebSession.checkLoginStatus(session)) {
            return "/wesite/view/sign/login";
        }

        model.addAttribute("ordercode", ordercode);
        model.addAttribute("paymoney", paymoney);
        model.addAttribute("paytype", paytype);
        return "/wesite/view/order/submit-result";
    }

    /**
     * 全局加入购物车
     *
     * @param priceid
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/cart/{priceid}", method = RequestMethod.GET)
    @ResponseBody
    public String showProductInfo(@PathVariable String priceid) throws Exception {
        JdataBean product = productService.getProductInfo(priceid);
        JsonReturn json = new JsonReturn();

        String userid = WebSession.getUserId(session);
        if (WebSession.checkWbUserAuth(userid)) {
            product.put("price", productService.findAppositePrice(userid, product.getString("id")));//价格等级
            JdataBean flashSale = promotionService.findFlashSaleByProductId(priceid, userid, Promotion.Platform.WE.ordinal());
            if (Objects.nonNull(flashSale)) {
                //单品促销有库存
                int amount = flashSale.getInt("amount");
                int inventory = product.getInt("amount");
                product.put("amount", amount > inventory ? inventory > 0 ? inventory : 0 : amount > 0 ? amount : 0);
                product.put("price", flashSale.get("price"));
            }
        } else {
            product.put("price", "");
        }

        json.putData(product.getDataMap());
        return json.toString();
    }

    @RequestMapping("/cart")
    @ResponseBody
    public String showCartList() throws Exception {
        String userid = WebSession.checkUserAuth(session);
        JsonReturn json = new JsonReturn();
        Map<String, Object> result = new HashMap<>();

        List<CartItem> items = orderService.findCartProducts(userid);
        int size = items.size();
        if (size > 0) {
            //购物车中有商品
            Map<String, CartItem> products = new HashMap<>();
            Map<String, Integer> tempProductStock = new HashMap<>();
            for (CartItem item : items) {
                String productid = String.valueOf(item.getProductid());

                products.put(productid, item);
                tempProductStock.put(productid, item.getAmount().intValue());
            }
            result = groupAndShow(userid, products, tempProductStock, session);
            session.setAttribute("we_totalPrice", result.get("totalPrice"));
        }

        result.put("count", size);
        json.putData(result);
        return json.toString();
    }

    private Map<String, Object> groupAndShow(String userid, Map<String, CartItem> items, Map<String, Integer> tempProductStock, HttpSession session) throws Exception {
        //商品分组
        Map<String, Object> group = group(userid, items);
        session.setAttribute("we_cart_promotions", group);
        //获取购物车中商品信息
        Map<String, Object> result = addPromotionProducts(userid, group, tempProductStock);
        session.setAttribute("we_tempProductStock", tempProductStock);

        BigDecimal totalPrice = (BigDecimal) result.get("totalPrice");
        if (items.size() > 0) {
            //获取购物车中无促销商品信息
            CartBean item = productService.findProducts(items, userid, Promotion.Platform.WE.ordinal());
            result.put("totalPrice", totalPrice.add(item.getTotalPrice()));
            result.put("list", item.getProducts());
        }
        return result;
    }

    private Map<String, Object> group(String userid, Map<String, CartItem> items) {
        Map<String, Object> tmpGroup = new HashMap<>();
        List<JdataBean> promotions = promotionService.findAll(userid, items.keySet(), Promotion.Platform.WE.ordinal());
        for (JdataBean promotion : promotions) {
            String type = promotion.getString("type");
            String productid = promotion.getString("productid");
            if ("COMMON".equalsIgnoreCase(type)) {
                continue;
            }

            if ("COMPLEX".equalsIgnoreCase(type)) {
                List<CartItem> products = (List<CartItem>) tmpGroup.get(type);
                if (products == null) {
                    products = new ArrayList<>();
                }
                products.add(items.get(productid));
                tmpGroup.put(type, products);
            } else {
                Map<String, List<CartItem>> groupItems = (Map<String, List<CartItem>>) tmpGroup.get(type);
                if (groupItems == null) {
                    groupItems = new LinkedHashMap<>();
                }

                String promotionId = promotion.getString("id");
                List<CartItem> products = groupItems.get(promotionId);
                if (Objects.isNull(products)) {
                    products = new ArrayList<>();
                }

                products.add(items.get(productid));
                groupItems.put(promotionId, products);
                tmpGroup.put(type, groupItems);
            }
            //移除促销商品
            items.remove(productid);
        }
        return tmpGroup;
    }

    private Map<String, Object> addPromotionProducts(String userid, Map<String, Object> group, Map<String, Integer> tempProductStock) throws Exception {
        Map<String, Object> result = new HashMap();
        BigDecimal totalPrice = BigDecimal.ZERO;

        Set<Map.Entry<String, Object>> typeEntries = group.entrySet();
        Iterator<Map.Entry<String, Object>> typeIterator = typeEntries.iterator();
        while (typeIterator.hasNext()) {
            Map.Entry<String, Object> typeNext = typeIterator.next();
            String type = typeNext.getKey();
            PromotionBuilder builder = PromotionBuilderFactory.get(type);
            List<CartBean> data = new ArrayList<>();
            if (type.equalsIgnoreCase("COMPLEX")) {
                List<CartItem> items = (List<CartItem>) typeNext.getValue();
                CartBean item = builder.getCartProducts(userid, null, items, Promotion.Platform.WE.ordinal(), tempProductStock);
                totalPrice = totalPrice.add(item.getTotalPrice());
                //获取满减促销、满赠促销、其他促销的商品信息
                result.put(type.toLowerCase(), item.getProducts());
            } else {
                Map<String, List<CartItem>> map = (Map<String, List<CartItem>>) typeNext.getValue();
                Set<Map.Entry<String, List<CartItem>>> promotionEntries = map.entrySet();
                Iterator<Map.Entry<String, List<CartItem>>> promotionIterator = promotionEntries.iterator();
                while (promotionIterator.hasNext()) {
                    Map.Entry<String, List<CartItem>> promotionNext = promotionIterator.next();
                    String promotionId = promotionNext.getKey();
                    List<CartItem> items = promotionNext.getValue();

                    CartBean item = builder.getCartProducts(userid, promotionId, items, Promotion.Platform.WE.ordinal(), tempProductStock);
                    data.add(item);

                    totalPrice = totalPrice.add(item.getTotalPrice());
                    //获取满减促销、满赠促销、其他促销的商品信息
                    result.put(type.toLowerCase(), data);
                }
            }
        }
        result.put("totalPrice", totalPrice);
        return result;
    }

    /**
     * 购物车同步
     */
    @RequestMapping(value = "syncart")
    @ResponseBody
    public String syncart(String promotionType, String promotionId, double price, CartItem item, HttpSession session) throws Exception {
        if (!WebSession.checkLoginStatus(session)) {
            throw new ClientException(CodeEnum.LoginOut);
        }

        String userid = WebSession.getWbUser(session).getUserid();
        orderService.updateCartCount(userid, String.valueOf(item.getId()), item.getCount());

        List<CartItem> items = new ArrayList<>();
        CartBean bean = null;
        if ("list".equalsIgnoreCase(promotionType)) {
            Map<String, CartItem> map = new HashMap<>();
            map.put(String.valueOf(item.getProductid()), item);
            bean = productService.findProducts(map, userid, Promotion.Platform.WE.ordinal());
        } else if ("complex".equalsIgnoreCase(promotionType)) {
            PromotionBuilder builder = PromotionBuilderFactory.get(promotionType.toUpperCase());
            items.add(item);
            Map<String, Integer> tempProductStock = (Map<String, Integer>) session.getAttribute("we_tempProductStock");
            bean = builder.getCartProducts(userid, null, items, Promotion.Platform.WE.ordinal(), tempProductStock);
        } else {
            Map<String, Object> group = (Map<String, Object>) session.getAttribute("we_cart_promotions");
            Map<String, List<CartItem>> temp = (Map<String, List<CartItem>>) group.get(promotionType.toUpperCase());
            items = temp.get(promotionId);

            Map<String, Integer> tempProductStock = (Map<String, Integer>) session.getAttribute("we_tempProductStock");
            for (CartItem entry : items) {
                tempProductStock.put(String.valueOf(entry.getProductid()), entry.getAmount().intValue());
                if (entry.getId() == item.getId()) {
                    entry.setCount(item.getCount());
                    entry.setCheck(item.isCheck());
                }
            }
            temp.put(promotionId, items);
            group.put(promotionType.toUpperCase(), temp);
            session.setAttribute("we_cart_promotions", group);
            PromotionBuilder builder = PromotionBuilderFactory.get(promotionType.toUpperCase());
            bean = builder.getCartProducts(userid, promotionId, items, Promotion.Platform.WE.ordinal(), tempProductStock);
        }

        JsonReturn json = new JsonReturn();
        HashMap<String, Object> data = new HashMap<>();
        data.put("type", promotionType);
        data.put("data", bean);
        BigDecimal totalPrice = (BigDecimal) session.getAttribute("we_totalPrice");
        if (item.isCheck()) {
            totalPrice = totalPrice.subtract(BigDecimal.valueOf(price));
        }
        totalPrice = totalPrice.add(bean.getTotalPrice());
        session.setAttribute("we_totalPrice", totalPrice);
        data.put("price", totalPrice);
        json.putData(data);
        return json.toString();
    }

    /**
     * 购物车同步
     */
    @RequestMapping(value = "toggleCart")
    @ResponseBody
    public String toggleCart(String promotionType, String promotionId, double price, CartItem item, HttpSession session) throws Exception {
        if (!WebSession.checkLoginStatus(session)) {
            throw new ClientException(CodeEnum.LoginOut);
        }

        String userid = WebSession.getWbUser(session).getUserid();

        JsonReturn json = new JsonReturn();
        List<CartItem> items = new ArrayList<>();
        CartBean bean = null;
        if ("list".equalsIgnoreCase(promotionType)) {
            Map<String, CartItem> map = new HashMap<>();
            map.put(String.valueOf(item.getProductid()), item);
            bean = productService.findProducts(map, userid, Promotion.Platform.WE.ordinal());
        } else if ("complex".equalsIgnoreCase(promotionType)) {
            PromotionBuilder builder = PromotionBuilderFactory.get(promotionType.toUpperCase());
            items.add(item);
            Map<String, Integer> tempProductStock = (Map<String, Integer>) session.getAttribute("we_tempProductStock");
            bean = builder.getCartProducts(userid, null, items, Promotion.Platform.WE.ordinal(), tempProductStock);
        } else {
            Map<String, Object> group = (Map<String, Object>) session.getAttribute("we_cart_promotions");
            Map<String, List<CartItem>> temp = (Map<String, List<CartItem>>) group.get(promotionType.toUpperCase());
            items = temp.get(promotionId);

            Map<String, Integer> tempProductStock = (Map<String, Integer>) session.getAttribute("we_tempProductStock");
            for (CartItem entry : items) {
                tempProductStock.put(String.valueOf(entry.getProductid()), entry.getAmount().intValue());
                if (entry.getId() == item.getId()) {
                    entry.setCount(item.getCount());
                    entry.setCheck(item.isCheck());
                }
            }
            temp.put(promotionId, items);
            group.put(promotionType.toUpperCase(), temp);
            session.setAttribute("we_cart_promotions", group);
            PromotionBuilder builder = PromotionBuilderFactory.get(promotionType.toUpperCase());
            bean = builder.getCartProducts(userid, promotionId, items, Promotion.Platform.WE.ordinal(), tempProductStock);
        }

        HashMap<String, Object> data = new HashMap<>();
        data.put("type", promotionType);
        data.put("data", bean);
        BigDecimal totalPrice = (BigDecimal) session.getAttribute("we_totalPrice");
        totalPrice = totalPrice.subtract(BigDecimal.valueOf(price)).add(bean.getTotalPrice());
        session.setAttribute("we_totalPrice", totalPrice);
        data.put("price", totalPrice);
        json.putData(data);
        return json.toString();
    }

    /**
     * 购物车同步
     */
    @RequestMapping(value = "toggleAll")
    @ResponseBody
    public String toggleAll(double price, boolean flag, HttpSession session) throws Exception {
        if (!WebSession.checkLoginStatus(session)) {
            throw new ClientException(CodeEnum.LoginOut);
        }
        JsonReturn json = new JsonReturn();

        Map<String, Object> group = (Map<String, Object>) session.getAttribute("we_cart_promotions");
        Set<Map.Entry<String, Object>> entries = group.entrySet();
        Iterator<Map.Entry<String, Object>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> next = iterator.next();
            String type = next.getKey();
            if ("complex".equalsIgnoreCase(type)) {
                List<CartItem> items = (List<CartItem>) group.get(type);
                for (CartItem item : items) {
                    item.setCheck(flag);
                }
            } else {
                Map<String, List<CartItem>> tmp = (Map<String, List<CartItem>>) group.get(type);
                Set<Map.Entry<String, List<CartItem>>> entrySet = tmp.entrySet();
                Iterator<Map.Entry<String, List<CartItem>>> entryIterator = entrySet.iterator();
                while (entryIterator.hasNext()) {
                    Map.Entry<String, List<CartItem>> entry = entryIterator.next();
                    List<CartItem> items = entry.getValue();
                    for (CartItem item : items) {
                        item.setCheck(flag);
                    }
                }
            }
        }
        session.setAttribute("we_cart_promotions", group);

        BigDecimal totalPrice = BigDecimal.ZERO;
        if (flag) {
            totalPrice = BigDecimal.valueOf(price);
        }
        session.setAttribute("we_totalPrice", totalPrice);
        json.putData(totalPrice);
        return json.toString();
    }

    /**
     * 购物车商品生成订单
     */
    @RequestMapping(value = "generateorder")
    @ResponseBody
    public String generateorder(@RequestBody List<CartItem> items) throws Exception {
        String userid = WebSession.getUserId(session);
        JsonReturn json = new JsonReturn();
        Map<Integer, CartItem> itemMap = new HashMap<>();

        int size = items.size();
        Integer[] ids = new Integer[size];
        for (int i = 0; i < size; i++) {
            CartItem item = items.get(i);
            if (item.getCount() < 0) {
                //商品购买数量为负数
                throw new ClientException(CodeEnum.PURCHASE_QUANTITY_ERROR);
            }

            ids[i] = item.getProductid();
        }

        items = orderService.findCartProducts(userid, ids);
        size = items.size();
        String[] cartIds = new String[size];
        for (int i = 0; i < size; i++) {
            CartItem item = items.get(i);
            itemMap.put(item.getProductid(), item);
            cartIds[i] = String.valueOf(item.getId());
        }

        //下架、价格、库存、控销校验
        Map<String, List<Map>> checkResult = orderService.checkProducts(userid, itemMap, Promotion.Platform.WE.ordinal());
        Set<Map.Entry<String, List<Map>>> entries = checkResult.entrySet();
        Iterator<Map.Entry<String, List<Map>>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, List<Map>> next = iterator.next();
            List<Map> products = next.getValue();
            if (!products.isEmpty()) {
                return json.toErrorString(this.getClass(), new ClientException(JSON.toJSONString(products), next.getKey()));
            }
        }

        //分组并处理商品
        CartBean bean = groupAndProcess(userid, itemMap, session);
        //生成订单
        String orderCode = orderService.generateOrder(userid, cartIds, bean);

        Map map = new HashMap();
        map.put("isInventoryChange", bean.isInventoryChange());
        map.put("orderCode", orderCode);
        json.putData(map);
        return json.toString();
    }

    private CartBean groupAndProcess(String userid, Map<Integer, CartItem> itemMap, HttpSession session) throws Exception {
        Map<String, Integer> tempProductStock = new HashMap<>();
        Map<Integer, JdataBean> productMap = new HashMap<>();

        List<JdataBean> products = productService.findProducts(userid, itemMap, Promotion.Platform.WE.ordinal());
        for (JdataBean product : products) {
            Integer productid = product.getInt("productid");
            CartItem item = itemMap.get(productid);
            product.put("count", item.getCount());
            productMap.put(productid, product);
            tempProductStock.put(String.valueOf(productid), item.getAmount().intValue());
        }
        //商品分组
        Map<String, Map<String, List<JdataBean>>> group = group(productMap, userid);
        //商品处理
        return process(group, tempProductStock, session);
    }

    private CartBean process(Map<String, Map<String, List<JdataBean>>> group, Map<String, Integer> tempProductStock, HttpSession session) throws Exception {
        CartBean result = new CartBean();
        BigDecimal totalPrice = BigDecimal.ZERO;
        BigDecimal restMoney = BigDecimal.ZERO;
        BigDecimal discountMoney = BigDecimal.ZERO;
        List<CartProductVO> products = new ArrayList<>();

        Set<Map.Entry<String, Map<String, List<JdataBean>>>> te = group.entrySet();
        Iterator<Map.Entry<String, Map<String, List<JdataBean>>>> ti = te.iterator();
        while (ti.hasNext()) {
            Map.Entry<String, Map<String, List<JdataBean>>> tn = ti.next();
            PromotionBuilder builder = PromotionBuilderFactory.get(tn.getKey());

            Map<String, List<JdataBean>> promotions = tn.getValue();
            Set<Map.Entry<String, List<JdataBean>>> entries = promotions.entrySet();
            Iterator<Map.Entry<String, List<JdataBean>>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                CartBean item = builder.process(iterator.next(), tempProductStock);
                //赠品数量发生变动
                Map<String, Integer> sessionProductStock = (Map<String, Integer>) session.getAttribute("we_tempProductStock");
                if (sessionProductStock != null && builder.checkInventoryChange(sessionProductStock, item)) {
                    result.setInventoryChange(true);
                }
                //订单项总价格
                BigDecimal unitTotalPrice = item.getTotalPrice();
                if (unitTotalPrice.compareTo(BigDecimal.ZERO) <= 0) {
                    //订单项总价格为负数或0
                    throw new ClientException(CodeEnum.Err);
                }
                totalPrice = totalPrice.add(unitTotalPrice);
                if (item.isAvailable()) {
                    //满减分摊后剩余价格
                    restMoney = restMoney.add(item.getRestMoney());
                    //满减优惠金额
                    discountMoney = discountMoney.add(item.getDiscountMoney());
                }
                products.addAll(item.getProducts());
            }
        }

        result.setTotalPrice(totalPrice);
        result.setDiscountMoney(discountMoney);
        result.setRestMoney(restMoney);
        result.setProducts(products);
        return result;
    }

    private Map<String, Map<String, List<JdataBean>>> group(Map<Integer, JdataBean> products, String userid) {
        Map<String, Map<String, List<JdataBean>>> tmpGroup = new HashMap<>();

        List<JdataBean> promotions = promotionService.findSpecificPromotions(userid, products.keySet(), Promotion.Platform.WE.ordinal());
        for (JdataBean promotion : promotions) {
            String type = promotion.getString("type");
            Integer productid = promotion.getInt("id");
            Map<String, List<JdataBean>> groupItems = tmpGroup.get(type);
            if (groupItems == null) {
                groupItems = new HashMap<>();
            }

            String promotionId = promotion.getString("promotionid");
            List<JdataBean> items = groupItems.get(promotionId);
            if (items == null) {
                items = new ArrayList<>();
            }

            items.add(products.get(productid));
            groupItems.put(promotionId, items);
            tmpGroup.put(type, groupItems);
            //移除满减、满赠促销商品
            products.remove(productid);
        }

        if (products.size() > 0) {
            Map<String, List<JdataBean>> groupItems = new HashMap<>();
            groupItems.put(null, new ArrayList<>(products.values()));
            tmpGroup.put("COMPLEX", groupItems);
        }
        return tmpGroup;
    }

}